import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 小结:
 * JDBC所涉及到的一些新的类/方法
 *
 * DataSource/MysqlDataSource描述了数据从哪来,一般来说,一个程序中只有一个DataSource对象就够了
 * Connection 描述了一个数据库连接对象,可以一个程序只有一个Connection,也可以一个程序有多个Connection.
 *
 * 第一种:一个Connection的情况,服务器气的的时候,创建Connection,当服务器每次收到一个请求就通过这个Connection来访问数据库.
 * 但是,如果服务器收到的请求时间间隔比较大,可能mtsql就会主动把连接断开.就需要程序员考虑重连的事情
 *
 * 第二种:服务器启动的时候不创建连接.当服务器收到请求的时候,再创建连接,然后再访问数据库.
 * 更常见一些,但是带来的问题就是每次创建连接就需要花费更多的时间
 * --实际上,JDBC的DataSource中对Connection进行了缓存
 * 某个Connection被close,不一定是真的把底层的连接释放,而是先偷偷放起来
 * 如果下次用到了,就直接拿出来用,就避免了重新建立连接的过程
 *
 * PrepareStatement描述一个SQL语句.
 * 核心功能:
 * 1.拼装SQL.setxxx
 * 2.执行SQL.executeUpdate executeQuery
 * ResultSet描述一个结果集合(表)
 * next()访问每一行
 * getxxx访问每一列
 *
 * close释放操作
 * ResultSet,PrepareStatement,Connection
 * 都需要手动释放
 */
public class TestJDBC {
    /**
     * 向上转型: 把子类实例使用一个父类引用指向(父类引用子类)
     * 向下转型:把父类实例使用一个子类引用指向(子类引用父类)
     *
     * @param args
     * @throws SQLException
     */
    public static void main(String[] args) throws SQLException {
//        1.先创建一个 Data Source 实例 (DataSource 就是 JDBC提供的类)
//        DataSource 就描述了数据的来源.(从哪个数据库来的,就需要在DataSource 中设置数据库的地址)
        DataSource  dataSource = new MysqlDataSource();

//        MysqlDataSource() 这个是实现DataSource的类,这个类是驱动包里面提供1的
//      interface DateSource 由JDBC提供的
//       不能直接创建DataSource的实例

//        通过这个代码告诉程序数据库服务器在哪,通过一个URL来描述服务器的地址.
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/java101?characterEncoding=utf8&useSSL=false");
        /**
         *  jdbc:mysql:
         *  协议名,对于jdbc来说是固定的
         *  127.0.0.1
         *  数据库服务器的IP地址,如果你的数据库服务器在本机上,就固定写作127.0.0.1
         *  3306
         *  服务器端口号,默认都是3306,不过安装mysql的时候,是可以配置的
         *  java101
         *  数据库名
         *  characterEncoding=utf8
         *  当前程序按照哪种字符集来理解数据库的数据
         *  useSSL=false
         *  是否对传输的数据加密,一般写成false就行了,不要写成true,不然有可能连不上数据库
         */

//        通过这个代码告知访问数据库的同户名.默认为root
        ((MysqlDataSource)dataSource).setUser("root");

//        通过这个代码告知访问数据库的密码.
        ((MysqlDataSource)dataSource).setPassword("109614");

//        就这样直白写,行不行?
//        MysqlDataSource dataSource1 = new MysqlDataSource();
//        dataSource1.setUrl();
//        dataSource1.setUser();
//        dataSource1.setPassword();

//        2.需要和数据库建立连接
//        通过网络和数据库进行链接操作,同时就会验证用户名密码
            Connection connection = dataSource.getConnection();//需要处理异常
        //这个代码就会发起网络请求.
//        相当于根据前面设置好的URL,User,Password尝试登陆到服务器上

        //3.构造SQL语句
        //以插入数据为例,往student表中插入数据
        String sql = "insert into student values(1,'张三')";//静态的sql
//        当前这个sql只是一个单纯的字符串,要想让mysql服务区能识别,还需要把这个字符串转成一个专门的对象
        PreparedStatement statement = connection.prepareStatement(sql);
//        PreparedStatement对象,能够帮助我们动态的构造出sql,同时也进行一些校验检查


        //4.执行sql
//        statement提供了两个系列的execute
        //一个是excuteUpdate,用于增加,删除,修改   =>返回值类型为int,表示影响到了多少行
        //一个是excuteQuery,用于进行查找,        =>ResultSet 表示返回的结果集(相当于一个表格)

        int ret = statement.executeUpdate();//返回的就是当前操作所影响的行数
        System.out.println("ret = "+ret);

//        5.释放相关资源
//        此处释放资源的顺序，要和申请的资源的顺序相反
        statement.close();
        connection.close();
        // 如果不关闭,可能会造成"资源泄漏"
//        如果不关闭链接,以及内部持有的socket文件描述符(网络编程以及IO流相关),都难以释放,
//        此时也会造成类似于内存泄漏的情况

        //java中内置了垃圾回收机制(CG)
//        CG能够保证不用的内存就被释放了

//        -------------------------------------
        //拼装 动态sql,程序运行时,确定sql中的具体内容
        /**
         * 静态和static这个关键字没任何关系
         * 静态:编译器就能确定的
         * 动态:编译器确定不了,运行时才能确定
         *
         */
    }


}
